# ex:ts=4:et:

# -*- coding: utf-8 -*-
#  Code comment plugin
#  This file is part of gedit
#
#  Copyright (C) 2005-2006 Igalia
#  Copyright (C) 2006 Matthew Dugan
#  Copyrignt (C) 2007 Steve Frécinaux
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor,
#  Boston, MA 02110-1301, USA.
import os
import random
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GtkSource', '4')
#gi.require_version('Tepl', '6')
#from gi.repository import GObject, Gio, Gtk, GtkSource, Gedit, Tepl ,GLib

from gi.repository import GObject, Gio, Gtk, GtkSource, Gedit ,GLib
import socket



try:
    import gettext
    gettext.bindtextdomain('gedit-plugins')
    gettext.textdomain('gedit-plugins')
    _ = gettext.gettext
except:
    _ = lambda s: s

# If the language is listed here we prefer block comments over line comments.
# Maybe this list should be user configurable, but just C comes to my mind...
block_comment_languages = [
    'c', 'chdr'
]

class qbs:
    host = "127.0.0.1"
    port = "27193"
    port_int = int(port)
    
    part1 =  '''<cmd-end/>
<cmd-start/>

<set-target-canvas>
<canvas-filename>CURRENT-CANVAS</canvas-filename>
</set-target-canvas>
<网络文件独占模式>
 <action--drop-package 
		       parent-uid = \"FIRST-CHOOSED\" 
                       x=\"500\" y =\"400\"  
		       XY-确定方法 = \"FIRST-CHOOSED > RIGHT-TOP > 0 > 0\"
                       flags = \"x-y-is-canvas-coordinate\"
                       filename=\"./package/000/pkg/src-location.better.pkg\" start-pos=\"48\" 
                       />
<sequence-operation-on-package>
     <package-uid>CREATED-JUST-NOW</package-uid> 

<port-index> 4  </port-index>   <port-value>'''

    part2 = "</port-value> <port-index> 5  </port-index>   <port-value>"
    part3 = "</port-value>"
    part4 = '''<package-uid>FIRST-CHOOSED</package-uid>
<get-package-or-jci-include-self/>
<发送canvas定位xml命令>
      <文件类型>'''
    part5 = "</文件类型>"
    part6 = '''</发送canvas定位xml命令>
</sequence-operation-on-package >
</网络文件独占模式>
<cmd-end/>   '''

    part_a = "["
    part_b = "]"

    part_head = ""
    part_end  = ""
    
    relative_path_1 = "/home/guest/qbs"
    relative_path_2 = "~/qbs"
    p1 = os.getenv('QBS_INSTALL_PATH_1') 
    if (p1  is not None):
        if len(p1) >=2:
            relative_path_1 = p1
    p2 = os.getenv('QBS_INSTALL_PATH_2')        
    if (p2  is not None):
        if len(p2) >=2:
            relative_path_2 = p2     

    print( relative_path_1)
    print( relative_path_2)
    
    relative_path_1_len = len(relative_path_1)
    relative_path_2_len = len(relative_path_2)

    start_string_id = "(%%"
    end_string_id   = "%%)"

    client_timeout_second = 2
    
    client_status = -1;

    
    client = socket.socket()
    client.settimeout(client_timeout_second)
    try:
        client.connect((host,port_int)) #建立一个链接，连接到本地的xxx端口
    except ConnectionRefusedError:
        client_status = 1;
    except:
        client_status = 100
    else:
        client_status = 0

    
    #print("client_status = " , client_status)    

   
    window = ""
    view = None

    
    def __init__(self):
        pass


    def get_relative_filename(self, fullname):
        #print(fullname);
        #print(self.relative_path_1)
        #print(self.relative_path_2)
        rf = ""
        if (fullname.startswith(self.relative_path_1)):
            rf = fullname[self.relative_path_1_len:]
            #print("--1--");
        elif  (fullname.startswith(self.relative_path_2)):   
            rf = fullname[self.relative_path_2_len:]
            #print("--2--");

        if rf == "":
            pass
        else:
            if (rf[0] == "/") :
                rf = "." + rf
            else:
                rf = "./" + rf

                
        return rf


    def reconnect_host():
        try:
            #qbs.client.shutdown(SHUT_RDWR)
            qbs.client.close()
            qbs.client = None
            
        except:
            print("client close --except-- in reconnection_host()");
            pass
        
        try:
            #print("create new connect ...")
            qbs.client = socket.socket()
            #print("create new connect 1")
            qbs.client.settimeout( qbs.client_timeout_second)
            #print("create new connect 2")
            qbs.client.connect((qbs.host, qbs.port_int)) #建立一个链接，连接到本地的xxx端口
            #print("create new connect ok")
        except ConnectionRefusedError:
            qbs.client_status = 1;
        except:
            qbs.client_status = 100
        else:
            qbs.client_status = 0

        #print("qbs.client_status = %d", qbs.client_status)
        pass

    def reconnect_host_if_necc():
        if qbs.client_status == 0:
            pass
        else:
            qbs.reconnect_host()
            pass
    

    def message_dialog(dialog_type, shortMsg, longMsg=None, parent=None,
                   buttons=Gtk.ButtonsType.OK, additional_buttons=None):

        d = Gtk.MessageDialog(parent=parent, flags=Gtk.DialogFlags.MODAL,  type=dialog_type, buttons=buttons)

        if additional_buttons:
            d.add_buttons(*additional_buttons)

        d.set_markup(shortMsg)

        if longMsg:
            if isinstance(longMsg, Gtk.Widget):
                widget = longMsg
            elif isinstance(longMsg, str):
                widget = Gtk.Label()
                widget.set_markup(longMsg)
            else:
                raise TypeError('"longMsg" must be a Gtk.Widget or a string')
  
            expander = Gtk.Expander(label = 'Click here for details')
            expander.set_border_width(6)
            expander.add(widget)
            d.vbox.pack_end(expander, True, True, 0)
    
        d.show_all()
        response = d.run()
        d.destroy()
        return response
    
        

class QbsJumpjumpAppActivatable(GObject.Object, Gedit.AppActivatable):

    #print(dir( Gedit.AppActivatable))  #ok
    
    app = GObject.Property(type=Gedit.App)
    '''
    print(dir(app))
    print(app.__class__.__name__)
    ff = GObject.Property(type=Gtk.Application) #active-window
    print(dir(ff))
    print(ff.__class__.__name__)
    #geditWindow = app.get_default().get_active_window()
    #geditWindow = (type(Gtk.Application)(app)).get_active_window()
    #geditWindow = (Gtk.Application)(app).get_active_window()
    #gapp = Gtk.Application (app);
    ##Gtk.Application gapp;
    ##gapp = app
    ###Gio.Application gapp;
    ###gapp = app
    gapp = Gtk.Application()
    print(dir(gapp))
    #gapp = (Gtk.Application)app
    #print(dir(gapp))
    geditWindow = super().app.get_default().get_active_window()
    
    geditWindow=gapp.get_default().get_active_window()
    geditWindow = gapp.get_active_window()
    geditView = app.get_default().get_active_window().get_active_view()
    '''
    
    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        "<Primary>M"  "<Primary><Shift>N"
        
        self.app.add_accelerator("F4", "win.createlink", None)
        self.app.add_accelerator("F12", "win.jumpdown", None)
        self.app.add_accelerator("F5", "win.jumpup", None)
        print("do_activate() QbsJumpjumpAppActivatable ")

    def do_deactivate(self):
        self.app.remove_accelerator("win.createlink", None)
        self.app.remove_accelerator("win.jumpdown", None)
        self.app.remove_accelerator("win.jumpup", None)
        print("do_deactivate() QbsJumpjumpAppActivatable ")

class QbsJumpjumpWindowActivatable(GObject.Object, Gedit.WindowActivatable):

    window = GObject.Property(type=Gedit.Window)
    qbs.window = window
    
    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        action = Gio.SimpleAction(name="createlink")
        action.connect('activate', lambda a, p: self.do_createlink())
        self.window.add_action(action)

        action = Gio.SimpleAction(name="jumpdown")
        action.connect('activate', lambda a, p: self.do_jumpdown(True))
        self.window.add_action(action)
        
        action = Gio.SimpleAction(name="jumpup")
        action.connect('activate', lambda a, p: self.do_jumpup(True))
        self.window.add_action(action)

        #print("do_activate() QbsJumpjumpWindowActivatable ")

    def do_deactivate(self):
        self.window.remove_action("createlink")
        self.window.remove_action("jumpup")
        self.window.remove_action("jumpdown")
        #print("do_deactivate() QbsJumpjumpWindowActivatable ")

    def do_update_state(self):
        view = self.window.get_active_view()
        qbs.view = view
        '''
        sensitive = False
        view = self.window.get_active_view()
        if view and hasattr(view, "code_comment_view_activatable"):
            sensitive = view.code_comment_view_activatable.doc_has_comment_tags()

        self.window.lookup_action('comment').set_enabled(sensitive)
        self.window.lookup_action('uncomment').set_enabled(sensitive)
        '''
        #print("do_update_state() QbsJumpjumpWindowActivatable ")

    def do_jumpup(self, unindent=False):
        view = self.window.get_active_view()
        qbs.view = view
        '''
        print(dir(view))
        buf = view.get_buffer()
        print(dir(buf))
        document = buf.get_document()
        sel = document.get_selection_bounds()
        currentPosMark = document.get_insert()
        '''
        if view and view.code_comment_view_activatable:
            view.code_comment_view_activatable.do_jumpup(view.get_buffer(), unindent)
            #print("do_jumpup()   ..2... QbsJumpjumpWindowActivatable ")
        
        #print("do_jumpup() 3 QbsJumpjumpWindowActivatable ");

        
    def do_jumpdown(self, unindent=False):
        view = self.window.get_active_view()
        qbs.view = view
        '''
        print(dir(view))
        buf = view.get_buffer()
        print(dir(buf))
        document = buf.get_document()
        sel = document.get_selection_bounds()
        currentPosMark = document.get_insert()
        '''
        if view and view.code_comment_view_activatable:
            view.code_comment_view_activatable.do_jumpdown(view.get_buffer(), unindent)
            #print("do_jumpdown()   ..2... QbsJumpjumpWindowActivatable ")
        
        #print("do_jumpdown() 3 QbsJumpjumpWindowActivatable ");
        
    def do_createlink(self, unindent=False):
        view = self.window.get_active_view()
        
        
        if view and view.code_comment_view_activatable:
            view.code_comment_view_activatable.do_createlink(view.get_buffer(), unindent)
            #print("do_createlink()   ..... QbsJumpjumpWindowActivatable ")
        #print("do_createlink() QbsJumpjumpWindowActivatable ")

class QbsJumpjumpViewActivatable(GObject.Object, Gedit.ViewActivatable):

    view = GObject.Property(type=Gedit.View)

    def __init__(self):
        self.popup_handler_id = 0
        GObject.Object.__init__(self)

    def do_activate(self):
        self.view.code_comment_view_activatable = self
        self.popup_handler_id = self.view.connect('populate-popup', self.populate_popup)

    def do_deactivate(self):
        if self.popup_handler_id != 0:
            self.view.disconnect(self.popup_handler_id)
            self.popup_handler_id = 0
        delattr(self.view, "code_comment_view_activatable")

    def populate_popup(self, view, popup):
        if not isinstance(popup, Gtk.MenuShell):
            return

        item = Gtk.SeparatorMenuItem()
        item.show()
        popup.append(item)

        item = Gtk.MenuItem.new_with_mnemonic(_("Co_mment Code"))
        item.set_sensitive(self.doc_has_comment_tags())
        item.show()
        item.connect('activate', lambda i: self.do_comment(view.get_buffer()))
        popup.append(item)

        item = Gtk.MenuItem.new_with_mnemonic(_('U_ncomment Code'))
        item.set_sensitive(self.doc_has_comment_tags())
        item.show()
        item.connect('activate', lambda i: self.do_comment(view.get_buffer(), True))
        popup.append(item)

    def doc_has_comment_tags(self):
        has_comment_tags = False
        doc = self.view.get_buffer()
        if doc:
            lang = doc.get_language()
            if lang is not None:
                has_comment_tags = self.get_comment_tags(lang) != (None, None)
        return has_comment_tags

    def get_block_comment_tags(self, lang):
        start_tag = lang.get_metadata('block-comment-start')
        end_tag = lang.get_metadata('block-comment-end')
        if start_tag and end_tag:
            return (start_tag, end_tag)
        return (None, None)

    def get_line_comment_tags(self, lang):
        start_tag = lang.get_metadata('line-comment-start')
        if start_tag:
            return (start_tag, None)
        return (None, None)

    def get_comment_tags(self, lang):
        if lang.get_id() in block_comment_languages:
            (s, e) = self.get_block_comment_tags(lang)
            if (s, e) == (None, None):
                (s, e) = self.get_line_comment_tags(lang)
        else:
            (s, e) = self.get_line_comment_tags(lang)
            if (s, e) == (None, None):
                (s, e) = self.get_block_comment_tags(lang)
        return (s, e)

    def forward_tag(self, iter, tag):
        iter.forward_chars(len(tag))

    def backward_tag(self, iter, tag):
        iter.backward_chars(len(tag))

    def get_tag_position_in_line(self, tag, head_iter, iter):
        found = False
        while (not found) and (not iter.ends_line()):
            s = iter.get_slice(head_iter)
            if s == tag:
                found = True
            else:
                head_iter.forward_char()
                iter.forward_char()
        return found

    def add_comment_characters(self, document, start_tag, end_tag, start, end):
        smark = document.create_mark("start", start, False)
        imark = document.create_mark("iter", start, False)
        emark = document.create_mark("end", end, False)
        number_lines = end.get_line() - start.get_line() + 1

        document.begin_user_action()

        for i in range(0, number_lines):
            iter = document.get_iter_at_mark(imark)
            if not iter.ends_line():
                document.insert(iter, start_tag)
                if end_tag is not None:
                    if i != number_lines -1:
                        iter = document.get_iter_at_mark(imark)
                        iter.forward_to_line_end()
                        document.insert(iter, end_tag)
                    else:
                        iter = document.get_iter_at_mark(emark)
                        document.insert(iter, end_tag)
            iter = document.get_iter_at_mark(imark)
            iter.forward_line()
            document.delete_mark(imark)
            imark = document.create_mark("iter", iter, True)

        document.end_user_action()

        document.delete_mark(imark)
        new_start = document.get_iter_at_mark(smark)
        new_end = document.get_iter_at_mark(emark)
        if not new_start.ends_line():
            self.backward_tag(new_start, start_tag)
        document.select_range(new_start, new_end)
        document.delete_mark(smark)
        document.delete_mark(emark)

    def remove_comment_characters(self, document, start_tag, end_tag, start, end):
        smark = document.create_mark("start", start, False)
        emark = document.create_mark("end", end, False)
        number_lines = end.get_line() - start.get_line() + 1
        iter = start.copy()
        head_iter = iter.copy()
        self.forward_tag(head_iter, start_tag)

        document.begin_user_action()

        for i in range(0, number_lines):
            if self.get_tag_position_in_line(start_tag, head_iter, iter):
                dmark = document.create_mark("delete", iter, False)
                document.delete(iter, head_iter)
                if end_tag is not None:
                    iter = document.get_iter_at_mark(dmark)
                    head_iter = iter.copy()
                    self.forward_tag(head_iter, end_tag)
                    if self.get_tag_position_in_line(end_tag, head_iter, iter):
                        document.delete(iter, head_iter)
                document.delete_mark(dmark)
            iter = document.get_iter_at_mark(smark)
            iter.forward_line()
            document.delete_mark(smark)
            head_iter = iter.copy()
            self.forward_tag(head_iter, start_tag)
            smark = document.create_mark("iter", iter, True)

        document.end_user_action()

        document.delete_mark(smark)
        document.delete_mark(emark)

    def do_createlink(self, document, unindent=False):
        #print("QbsJumpjumpViewActivatable  do_createlink() begin ...  ");
        sel = document.get_selection_bounds()
        currentPosMark = document.get_insert()
        deselect = False
        if sel != ():
            (start, end) = sel
            if start.ends_line():
                start.forward_line()
            elif not start.starts_line():
                start.set_line_offset(0)
            if end.starts_line():
                end.backward_char()
            elif not end.ends_line():
                end.forward_to_line_end()
        else:
            deselect = True
            start = document.get_iter_at_mark(currentPosMark)
            start.set_line_offset(0)
            end = start.copy()
            end.forward_to_line_end()


        rs =''.join(random.sample('zyxwvutsrqponmlkjihgfedcba_ZYXWVUTSRQPONMLKJIHGFEDCBA 123457890',20))
        #print(rs) #ok

        ffin = document.get_file()
        #attr = dir(ffin)   #ok
        #print(attr) #ok

        loc = ffin.get_location()
        #print(dir(loc)) #ok

        #print("======")
        fullpathfilename = loc.get_path()
        onlyfilename = loc.get_basename ()
        #print(fullpathfilename)
        #print(onlyfilename)
        #print(loc.get_path()) #ok
        #print(loc.get_basename ()) #ok
        
        #print(loc.get_relative_path())
        #print(loc.get_full_name())
        #print(loc.get_short_name())
        '''      
        print(ffin.get_path())  #  no attribution err
        print(ffin.get_basename ())#  no attribution err
        #print(ffin.get_full_name())#  no attribution err
        print(ffin.get_short_name())#  no attribution err
        '''

        rfn = qbs.get_relative_filename(qbs,fullpathfilename);
        #print("rfn is ======= " , rfn)

        if (rfn == ""):
            #print(dir(self))  #ok
            text = "file:" + fullpathfilename +" is not under path:\n"    + "(try: create a symlink to target dir under QBS install path, and then open file by following the symlink)" \
                + "\n\t1:" \
                +  qbs.relative_path_1 \
                + "\n\t2:" + qbs.relative_path_2  \
                + "\nif QBS install path is not listed above, need append env by: \n" \
                + "export QBS_INSTALL_PATH_1=\"/.../.../..\"\n"  \
                + "export QBS_INSTALL_PATH_2=\"~/.../...\"\n" 
            #qbs.message_dialog(Gtk.MessageType.ERROR, text,None, qbs.window, buttons=Gtk.ButtonsType.NONE);
            qbs.message_dialog(Gtk.MessageType.ERROR, text,None, None, buttons=Gtk.ButtonsType.NONE);
            pass
        else:

            #print(dir(self))  #ok
            #qbs.message_dialog(Gtk.MessageType.ERROR, "ok, the file is under qbs install path", self.window, buttons=Gtk.ButtonsType.NONE); #err
            #qbs.message_dialog(Gtk.MessageType.ERROR, "ok, the file is under qbs install path",None,None  , buttons=Gtk.ButtonsType.NONE);  #ok
            
            pass

        qbs.reconnect_host_if_necc()
        if (qbs.client_status == 0):
            #print("connection is ready")
            qbs.part_head = ""
            qbs.part_end  = ""
            lang = document.get_language()
            if lang is None:
                pass
            else:
                (start_tag, end_tag) = self.get_comment_tags(lang)
                if not start_tag:
                    pass
                else:
                    qbs.part_head = start_tag
                if not end_tag:
                    pass
                else:
                    qbs.part_end = end_tag           
                
                pass

            temptxt = "\n" + qbs.part_head + qbs.part_a + rs + qbs.part_b + qbs.start_string_id + "    "  + qbs.end_string_id + qbs.part_end
            document.insert(end, temptxt)
            end.backward_chars(6)
            document.place_cursor(end)

            temptxt =  qbs.part1 + rs + qbs.part2 +  rfn + qbs.part3 + qbs.part4 + "c or cpp" + qbs.part5 + qbs.part6
            #print("temptxt is ====" , temptxt)
            try:
                qbs.client.sendall(temptxt.encode("utf-8"))
            except:
                qbs.client_status = 5
                qbs.message_dialog(Gtk.MessageType.ERROR, "send data failed, will retry next time. ",None, None, buttons=Gtk.ButtonsType.NONE);
            if (qbs.client_status == 0):
                try:
                    recv_string = qbs.client.recv(1024)
                    document.insert_at_cursor(recv_string.decode("utf-8"))
                except:
                    qbs.message_dialog(Gtk.MessageType.ERROR, "send data ok, but get no response, firewall or something else. ",None, None, buttons=Gtk.ButtonsType.NONE);
            
            
            pass
        else:
            #print("connection is not ready")
            qbs.message_dialog(Gtk.MessageType.ERROR, "connection is not ready",None,None  , buttons=Gtk.ButtonsType.NONE);
            pass
        

        #GLib.free(fullpathfilename) #param err
        

        return
    
        lang = document.get_language()
        if lang is None:
            return

        (start_tag, end_tag) = self.get_comment_tags(lang)

        if not start_tag and not end_tag:
            return

        if unindent:       # Select the comment or the uncomment method
            new_code = self.remove_comment_characters(document,
                                                      start_tag,
                                                      end_tag,
                                                      start,
                                                      end)
        else:
            new_code = self.add_comment_characters(document,
                                                   start_tag,
                                                   end_tag,
                                                   start,
                                                   end)

        if deselect:
            oldPosIter = document.get_iter_at_mark(currentPosMark)
            document.select_range(oldPosIter,oldPosIter)
            document.place_cursor(oldPosIter)

    def do_jumpdown(self, document, unindent=False):
        #print("do_jumpdown() 1   QbsJumpjumpViewActivatable ")
        sel = document.get_selection_bounds()
        currentPosMark = document.get_insert()
        deselect = False
        #print(dir(document)) #ok
        deselect = True
        start = document.get_iter_at_mark(currentPosMark)
        #start.set_line_offset(0)
        end = start.copy()
        #end.forward_to_line_end()

        start_line = start.get_line()
        start_byte_col  = start.get_line_index()  #Returns the byte index of the iterator, UTF-8,require a variable number of bytes to represent
        
        target_line = start_line + 100
        #print(start_line); print(target_line); #ok debug only
        end.forward_lines(100)    #ok 
        #document.place_cursor(end) #ok debug only


        offset_line = 0;
        offset_col = 0;
        strpart = document.get_text(start, end, True)

        
        head_and_end_iter_turple = start.forward_search("%%)",  Gtk.TextSearchFlags.TEXT_ONLY , end)
        if head_and_end_iter_turple is None:
            print("can not find %%)")
            pass
        else:
            print("find %%)")
            start_string_head_iter = head_and_end_iter_turple[0]
            start_string_tail_iter = head_and_end_iter_turple[1]
            start_string_head_iter__line = start_string_head_iter.get_line()
            document.place_cursor(start_string_tail_iter)
            qbs.view.scroll_to_iter(start_string_head_iter, 0.2, False, 0, 0)

            search_limit_item = start_string_head_iter.copy()
            if (( start_string_head_iter__line - 100) < 0):
                search_limit_item.set_line(0);
            else:
                search_limit_item.set_line( start_string_head_iter__line - 100)
                
            second_head_and_end_iter_turple = start_string_head_iter.backward_search("(%%",  Gtk.TextSearchFlags.TEXT_ONLY , search_limit_item)
            if second_head_and_end_iter_turple is None:
                print("can not find (%%")
                pass
            else:
                print("find (%%")
                end_string_head_iter = second_head_and_end_iter_turple[1]
                str_need_send = document.get_text(end_string_head_iter, start_string_head_iter, True)
                #str_need_send = str_need_send [3:-3]
                print(str_need_send)
                qbs.reconnect_host_if_necc()
                if (qbs.client_status == 0):
                    try:
                    
                        qbs.client.sendall(str_need_send.encode("utf-8"))
                    except:
                        qbs.message_dialog(Gtk.MessageType.ERROR, "send data failed, will retry next time. ",None, None, buttons=Gtk.ButtonsType.NONE);
                        qbs.client_status = 5
                    pass
                else:
                    print(qbs.client_status)
                    qbs.message_dialog(Gtk.MessageType.ERROR, "--connection is not ready",None,None  , buttons=Gtk.ButtonsType.NONE);
                    pass
                pass
                
                pass




            
            pass
            
        

    def do_jumpup(self, document, unindent=False):
        #print("do_jumpup() 1   QbsJumpjumpViewActivatable ")
        sel = document.get_selection_bounds()
        currentPosMark = document.get_insert()
        deselect = False
        #print(dir(document)) #ok
        deselect = True
        start = document.get_iter_at_mark(currentPosMark)
        #start.set_line_offset(0)
        end = start.copy()
        #end.forward_to_line_end()

        start_line = start.get_line()
        start_byte_col  = start.get_line_index()  #Returns the byte index of the iterator, UTF-8,require a variable number of bytes to represent
        
        target_line = start_line - 100
        #print(start_line); print(target_line); #ok debug only
        end.backward_lines(100)    #ok 
        #document.place_cursor(end) #ok debug only


        head_and_end_iter_turple = start.backward_search("(%%",  Gtk.TextSearchFlags.TEXT_ONLY , end)
        if head_and_end_iter_turple is None:
            print("can not find (%% ")
            pass
        else:
            start_string_head_iter = head_and_end_iter_turple[0]
            start_string_head_iter__line = start_string_head_iter.get_line()
            document.place_cursor(start_string_head_iter)
            qbs.view.scroll_to_iter(start_string_head_iter, 0.2, False, 0, 0)

            search_limit_item = start_string_head_iter.copy()
            search_limit_item.set_line( start_string_head_iter__line + 100)

            second_head_and_end_iter_turple = start_string_head_iter.forward_search("%%)",  Gtk.TextSearchFlags.TEXT_ONLY , search_limit_item)
            if second_head_and_end_iter_turple is None:
                pass
            else:
                end_string_tail_iter = second_head_and_end_iter_turple[1]
                str_need_send = document.get_text(start_string_head_iter, end_string_tail_iter, True)
                str_need_send = str_need_send [3:-3]
                print(str_need_send)
                qbs.reconnect_host_if_necc()
                if (qbs.client_status == 0):
                    try:
                    
                        qbs.client.sendall(str_need_send.encode("utf-8"))
                    except:
                        qbs.message_dialog(Gtk.MessageType.ERROR, "send data failed, will retry next time. ",None, None, buttons=Gtk.ButtonsType.NONE);
                        qbs.client_status = 5
                    pass
                else:
                    print(qbs.client_status)
                    qbs.message_dialog(Gtk.MessageType.ERROR, "--connection is not ready",None,None  , buttons=Gtk.ButtonsType.NONE);
                    pass
                pass
                
                pass




            
            pass


        
            
# ex:ts=4:et: